package com.atguigu.java3;

import com.atguigu.java2.Employee;
import com.atguigu.java2.EmployeeData;
import org.junit.Test;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author : leimingchao
 * @Description:
 *
 *      测试Stream的终止操作
 * @date Date : 2021年06月19日 18:13
 */
public class StreamAPITest3 {

    /**
     * 1-匹配与查找
     *      allMatch(Predicate p) 检查是否匹配所有元素
     *      anyMatch(Predicate p) 检查是否至少匹配一个元素
     *      noneMatch(Predicate p) 检查是否没有匹配所有元素
     *      findFirst() 返回第一个元素
     *      findAny() 返回当前流中的任意元素
     */
    @Test
    public void test() {
        List<Employee> employees = EmployeeData.getEmployees();
        //练习所有员工的年龄都大于18岁
        boolean allMatch = employees.stream().allMatch(employee -> employee.getAge() > 18);
        System.out.println(allMatch);
        System.out.println("*****************************************************");
        //是否存在员工的工资大于10000
        boolean anyMatch = employees.stream().anyMatch(employee -> employee.getSalary() > 10000);
        System.out.println(anyMatch);
        System.out.println("*****************************************************");
        //是否存在员工姓"雷"
        boolean noneMatch = employees.stream().noneMatch(employee -> employee.getName().startsWith("雷"));
        System.out.println(noneMatch);
        System.out.println("*****************************************************");
        Optional<Employee> employee = employees.stream().findFirst();
        System.out.println(employee);
        System.out.println("*****************************************************");
        Optional<Employee> any = employees.stream().findAny();
        System.out.println(any);
        System.out.println("*****************************************************");
        Optional<Employee> any2 = employees.parallelStream().findAny();
        System.out.println(any2);
        System.out.println("*****************************************************");
    }

    /**
     *     count() 返回流中元素总数
     *     max(Comparator c) 返回流中最大值
     *     min(Comparator c) 返回流中最小值
     *     forEach(Consumer c)
     *     内部迭代(使用 Collection 接口需要用户去做迭代称为外部迭代。相反，Stream API 使用内部迭代——它帮你把迭代做了)
     *
     */
    @Test
    public void test2() {
        List<Employee> employees = EmployeeData.getEmployees();
        long count = employees.stream().filter(employee -> employee.getSalary() > 5000).count();
        System.out.println(count);
        System.out.println("*****************************************************");
        Optional<Double> optional = employees.stream().map(Employee::getSalary).max(Double::compare);
        System.out.println(optional);
        System.out.println("*****************************************************");
        Optional<Employee> min = employees.stream().min((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()));
        System.out.println(min);
        System.out.println("*****************************************************");
        Optional<Employee> min2 = employees.stream().min(Comparator.comparingDouble(Employee::getSalary));
        System.out.println(min2);
        System.out.println("*****************************************************");
        employees.stream().forEach(System.out::println);
        System.out.println();
        //使用集合的遍历操作
        employees.forEach(System.out::println);

    }

    /**
     * 2-归约
     *      reduce(T iden, BinaryOperator b)
     *          可以将流中元素反复结合起来，得到一个值。返回 T
     *
     *      reduce(BinaryOperator b)
     *          可以将流中元素反复结合起来，得到一个值。返回 Optional<T>
     */
    @Test
    public void test3() {
        //1.计算1-10自然数的和
        List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
        System.out.println(list.stream().reduce(0, Integer::sum));
        System.out.println("********************************************");
        //2.计算公司所有员工的工资总和
        List<Employee> employees = EmployeeData.getEmployees();
        Optional<Double> optional = employees.stream().map(Employee::getSalary).reduce(Double::sum);
        System.out.println(optional);
    }

    /**
     * 3-收集
     *      collect(Collector c):将流转换为其他形式。接收一个 Collector接口的实现，用于给Stream中元素做汇总的方法
     *
     */
    @Test
    public void test4() {
        //练习1：查找工资大于6000的员工，结果返回为一个List或者Set
        List<Employee> employees = EmployeeData.getEmployees();
        employees.stream()
                .filter(employee -> employee.getSalary() > 6000)
                .collect(Collectors.toList())
                .forEach(System.out::println);
        System.out.println("*************************************");
        employees.stream()
                .filter(employee -> employee.getSalary() > 6000)
                .collect(Collectors.toSet()).forEach(System.out::println);
    }

    @Test
    public void test5() {
        //总数
        Long count = EmployeeData.getEmployees()
                .stream()
                .collect(Collectors.counting());
        System.out.println(count);
        System.out.println("*************************************");
        //平均值
        Double avg = EmployeeData.getEmployees()
                .stream()
                .collect(Collectors.averagingDouble(Employee::getSalary));
        System.out.println(avg);
        System.out.println("*************************************");
        //总和
        Double sum = EmployeeData.getEmployees()
                .stream()
                .collect(Collectors.summingDouble(Employee::getSalary));
        System.out.println(sum);
        System.out.println("*************************************");
        //最大值
        Optional<Employee> max = EmployeeData.getEmployees()
                .stream()
                .collect(Collectors.maxBy(Comparator.comparingDouble(Employee::getSalary)));
        System.out.println(max.get());
        System.out.println("*************************************");
        //最小值
        Optional<Employee> min = EmployeeData.getEmployees()
                .stream()
                .collect(Collectors.minBy(Comparator.comparingDouble(Employee::getSalary)));
        System.out.println(min.get());
    }

    /**
     * 分组
     */
    @Test
    public void test6() {
        Map<Integer, List<Employee>> map = EmployeeData.getEmployees()
                .stream()
                .collect(Collectors.groupingBy(Employee::getAge));
        map.forEach((key,value) ->System.out.println(key + "==>" + value));
    }

    /**
     * 多级分组
     */
    @Test
    public void test7() {
        Map<Integer, Map<Integer, List<Employee>>> map = EmployeeData.getEmployees()
                .stream()
                .collect(Collectors.groupingBy(Employee::getAge, Collectors.groupingBy(Employee::getId)));
        map.forEach((key,value) ->System.out.println(key + "==>" + value));
    }

    /**
     * 分区
     */
    @Test
    public void test8() {
        Map<Boolean, List<Employee>> map = EmployeeData.getEmployees()
                .stream()
                .collect(Collectors.partitioningBy(e -> e.getSalary() > 5000));
        map.forEach((key,value) ->System.out.println(key + "==>" + value));

    }

    /**
     *
     */
    @Test
    public void test9() {
        DoubleSummaryStatistics summaryStatistics = EmployeeData.getEmployees()
                .stream()
                .collect(Collectors.summarizingDouble(Employee::getSalary));
        double sum = summaryStatistics.getSum();
        System.out.println(sum);
        long count = summaryStatistics.getCount();
        System.out.println(count);
        double max = summaryStatistics.getMax();
        System.out.println(max);
        double min = summaryStatistics.getMin();
        System.out.println(min);
        double average = summaryStatistics.getAverage();
        System.out.println(average);

    }

    @Test
    public void test10() {
        String collect = EmployeeData.getEmployees()
                .stream()
                .map(Employee::getName)
                .collect(Collectors.joining());
        System.out.println(collect);
        System.out.println("**************************");
        String str = EmployeeData.getEmployees()
                .stream()
                .map(Employee::getName)
                .collect(Collectors.joining(",","===","==="));
        System.out.println(str);
    }

    @Test
    public void test11() {
        List<String> servers = new ArrayList<>();
        servers.add("tomcat");
        servers.add("jetty");
        servers.add("undertow");
        String collect = servers.parallelStream().collect(Collectors.collectingAndThen(Collectors.joining(","), String::toUpperCase));
        System.out.println(collect);
    }
}
